-
-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for custom fonts #421
Conversation
|
I added a |
Do we want to allow custom selection of the fallback, or multiple fonts in general? There are several ways this could be done (such as allowing the font name string to contain multiple fonts, allowing an array of font names to be used, or allow chaining of .font() to add fonts rather than replacing). |
I liked the idea of chaining Now a
Text("Hello, world!")
.font(.custom("Marker Felt", size: 17))
.font(.system(.body, design: .serif)) The above snippet will use Marker Felt if available in the UA, or the default font-family: 'Marker Felt', Cambria, 'Hoefler Text', Utopia, ...; I also improved the sanitizer to sanitize identifiers and strings separately. |
_fontPath = [newFont] + _fontPath.filter { $0 != newFont } | ||
} else { | ||
_fontPath = [] | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this file be split by any chance to avoid the linter warning? Maybe some extensions or types moved to separate files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll split it into more manageable files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems legit 👍
input.starts(with: "'") || input.starts(with: "\"") | ||
&& !input.dropFirst().dropLast().allSatisfy(isStringContent) | ||
&& input.last == input.first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this function? It isn't called anywhere. Additionally, the logic isn't correct.
input.starts(with: "'") || input.starts(with: "\"") | |
&& !input.dropFirst().dropLast().allSatisfy(isStringContent) | |
&& input.last == input.first | |
(input.starts(with: "'") || input.starts(with: "\"")) | |
&& input.dropFirst().dropLast().allSatisfy(isStringContent) | |
&& input.last == input.first |
/// Sanitizes a quoted string. | ||
enum StringValue: Sanitizer { | ||
static func isStringContent(_ char: Character) -> Bool { | ||
char != "'" && char != "\"" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline and backslash can also cause problems.
char != "'" && char != "\"" | |
!"'\"\n\\".contains(char) |
static func sanitize(_ input: String) -> String { | ||
input.filter(isIdentifierChar) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are additional restrictions for the first character of identifiers. I'm not sure if it really matters here, but I'd at least add a comment in case this code gets reused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the sanitizers to use the CSS 2.1 grammar.
@@ -64,6 +64,13 @@ struct TextDemo: View { | |||
) | |||
.multilineTextAlignment(alignment) | |||
} | |||
Text("Custom Font") | |||
.font(.custom("\"Marker Felt\"", size: 17)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The font-family
generated by this has just the custom font. There should always be a fallback, even if one isn't specified explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a default fallback of .body
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
|
Resolved 3. Do you have suggestions on how to fix the other 2? I can't figure out why its matching numbers in the identifier parsing. |
|
Thank you for tracking those issues down! Turns out NSRegularExpression uses |
@ezraberch would you have a moment to have another quick look? I personally don't have any objections for this code to be merged, but I appreciate very detailed reviews from you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionality looks good now.
I'm still unsure why Identifier.sanitize and StringValue.validate exist, as they're not called anywhere (other than by tests). The Sanitizer protocol does require them, but that seems unnecessary as well.
Yeah it might be unnecessary. I just thought the functionality may be useful in the future when we are sanitizing more areas. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
@ezraberch thanks again for your feedback on this and other PRs and your previous contributions! Would you be interested in joining our maintainers team? This would allow you to give review approvals for example. |
Sure. |
Adds a
.custom
member toFont
, which will pass the value tofont-family
in the DOM renderer.